#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>

#include "cJSON.h"

/* 函数申明 */
void contact_show_menu(void);
void contact_add(void);
void contact_display(void);
void contact_delete(void);
void contact_lookup(void);
void contact_modify(void);
void contact_clear(void);
void contact_load(void);
void contact_sync(void);
void contact_continue(void);

/* 全局变量定义 */
cJSON *root;

int main(int argc, char **argv)
{
    int menu = -1;

    contact_load();

    while(1)
    {
        contact_show_menu();
        scanf("%d", &menu);

        switch(menu)
        {
            case 1:         // 1. 添加联系人
                contact_add();
                printf("成功添加联系人.\r\n");
                break;
            case 2:         // 2. 显示联系人
                contact_display();
                break;
            case 3:         // 3. 删除联系人
                contact_delete();
                printf("成功删除联系人.\r\n");
                break;
            case 4:         // 4. 查找联系人
                contact_lookup();
                break;
            case 5:         // 5. 修改联系人
                contact_modify();
                printf("成功修改联系人.\r\n");
                break;
            case 6:         // 6. 清空通讯录
                contact_clear();
                printf("成功清空通讯录.\r\n");
                break;
            case 0:         // 0. 退出通讯录
                printf("成功退出系统.\r\n");
                return 0;
            default:        // 异常输入
                printf("异常输出, 强制退出系统.\r\n");
                return 0;
                break;
        }

        menu = -1;
        contact_continue();
    }

    return 0;
}

void contact_show_menu(void)
{
    system("clear");
    printf("*****************************\r\n");
    printf("*****   1. 添加联系人   *****\r\n");
    printf("*****   2. 显示联系人   *****\r\n");
    printf("*****   3. 删除联系人   *****\r\n");
    printf("*****   4. 查找联系人   *****\r\n");
    printf("*****   5. 修改联系人   *****\r\n");
    printf("*****   6. 清空通讯录   *****\r\n");
    printf("*****   0. 退出通讯录   *****\r\n");
    printf("*****************************\r\n");
    printf(">>> ");
}

void contact_add(void)
{
    char phone[32];
    char name[32];
    cJSON *new_person;

    printf("请输入新联系人信息, 格式: 姓名 电话\r\n");
    printf(">>> ");
    scanf("%s %s", name, phone);

    /* 创建新联系人 */
    new_person = cJSON_CreateObject();
    cJSON_AddStringToObject(new_person, "name", name);
    cJSON_AddStringToObject(new_person, "phone", phone);

    /* 添加到通讯录 */
    cJSON_AddItemToObject(root, name, new_person);

    /* 同步通讯录到本地 */
    contact_sync();
}

void contact_display(void)
{
    cJSON *tmp;
    cJSON *people;
    cJSON *name;
    cJSON *phone;

    printf("%-12s %-20s\r\n", "name", "phone");
    printf("-----------------------------\r\n");

    tmp = cJSON_GetObjectItem(root, "app");
    while(tmp->next != NULL)
    {
        tmp = tmp->next;
        people = cJSON_GetObjectItem(root, tmp->string);
        name = cJSON_GetObjectItem(people, "name");
        phone = cJSON_GetObjectItem(people, "phone");
        printf("%-12s %-20s\r\n", name->valuestring, phone->valuestring);
    }
}

void contact_delete(void)
{
    char sname[32];
    cJSON *people;

    printf("请输入需要删除的联系人姓名:\r\n");
    printf(">>> ");
    scanf("%s", sname);

    people = cJSON_GetObjectItem(root, sname);
    if(people == NULL)
    {
        printf("查无此人\r\n");
        return;
    }

    cJSON_DeleteItemFromObject(root, sname);
    contact_sync();
}

void contact_lookup(void)
{
    char sname[32];
    cJSON *people;
    cJSON *name;
    cJSON *phone;

    printf("请输入需要查找的联系人姓名:\r\n");
    printf(">>> ");
    scanf("%s", sname);

    people = cJSON_GetObjectItem(root, sname);
    if(people == NULL)
    {
        printf("查无此人\r\n");
        return;
    }

    name = cJSON_GetObjectItem(people, "name");
    phone = cJSON_GetObjectItem(people, "phone");
    printf("%-12s %-20s\r\n", "name", "phone");
    printf("-----------------------------\r\n");
    printf("%-12s %-20s\r\n", name->valuestring, phone->valuestring);
}

void contact_modify(void)
{
    char sname[32];
    char name[32];
    char phone[32];
    cJSON *people;

    printf("请输入需要修改的联系人姓名:\r\n");
    printf(">>> ");
    scanf("%s", sname);

    people = cJSON_GetObjectItem(root, sname);
    if(people == NULL)
    {
        printf("查无此人\r\n");
        return;
    }

    printf("请输入联系人新信息, 格式: 姓名 电话\r\n");
    printf(">>> ");
    scanf("%s %s", name, phone);

    cJSON_DeleteItemFromObject(people, "name");
    cJSON_AddStringToObject(people, "name", name);

    cJSON_DeleteItemFromObject(people, "phone");
    cJSON_AddStringToObject(people, "phone", phone);
    contact_sync();

}

void contact_clear(void)
{
    cJSON_Delete(root);
    root = cJSON_CreateObject();
    cJSON_AddStringToObject(root, "app", "contact");
    contact_sync();
}

void contact_load(void)
{
    char *result;
    int length;
    char *name = "list.json";
    FILE *fp;
    int len;

    /* 打开本地联系人信息文件*/
    fp = fopen(name, "rb");
    if (!fp)
    {
        printf("err: open %s file failed!\r\n", name);
        return;
    }

    /* 偏移到文件最后, 查询当前偏移值则为文件大小 */
    fseek(fp, 0L, SEEK_END);
    length = ftell(fp);

    /* 偏移回文件头 */
    fseek(fp, 0L, SEEK_SET);
    result = malloc(length);
    len = fread(result, 1, length, fp);
    if(len != length)
    {
        printf("err: %s read failed! len = %d, length = %d\r\n", name, (int)len, length);
        return;
    }

    root = cJSON_Parse(result);

    fclose(fp);
}

void contact_sync(void)
{
    char *result;
    int length;                 // 创建得到的 JSON 字符串的长度
    char *name = "list.json";   // 输出的 JSON 文件名
    FILE *fp;                   // 输出的 JSON 文件句柄
    int len;                    // 实际写入文件中的数据长度

    result = cJSON_Print(root);
    length = strlen(result);

    fp = fopen(name, "wb");
    if (!fp)
    {
        printf("err: open %s file failed!\r\n", name);
        return;
    }

    len = fwrite(result, 1, length, fp);
    if(len != length)
    {
        printf("err: %s write failed! len = %d, length = %d\r\n", name, (int)len, length);
        return;
    }
    fclose(fp);
}

void contact_continue(void)
{
    char c;
    printf("按任意键继续.\r\n");
    getchar();                  // 接收上面没有接收的换行符
    getchar();                  // 等待任意字符
}

